package com.diandian.backend.file.service;

import com.diandian.backend.file.resp.FileInfoRespFile;
import com.diandian.backend.file.resp.MultiFileUploadResp;
import com.diandian.base.boot.starter.response.BaseResult;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

/**
 * 阿里云文件存储操作
 */
@Service
public class MinIOFileService extends AbsFileService {

    private static final Logger logger = LoggerFactory.getLogger(MinIOFileService.class);

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

    @Autowired
    private FileCheckService fileCheckService;

    @Autowired
    private MinioClient client;

    @Value("${oss.minio.bucketName}")
    private String bucketName;

    @Value("${oss.minio.baseSchema}")
    private String baseSchema;

    @Value("${oss.minio.baseUrl}")
    private String baseUrl;

    @Value("${oss.minio.allowedExtension}")
    private String allowedExtension;

    @Value("${oss.minio.maxFileSize}")
    private long maxFileSize;

    @Override
    public FileInfoRespFile saveFile(MultipartFile file) {

        // 2. 校验文件格式是否允许
        String fileOriginalName = file.getOriginalFilename();
        String extension = FilenameUtils.getExtension(fileOriginalName);
        if(!fileCheckService.extensionCheck(extension, allowedExtension)){
            return new FileInfoRespFile(false, "暂不支持" + extension + "格式的文件");
        }

        // 3. 文件大小校验
        if(!fileCheckService.fileSizeCheck(file, maxFileSize)){
            return new FileInfoRespFile(false, "文件大小超过限制");
        }

        // 构建存储文件名/存储path
        String saveFileName = UUID.randomUUID().toString().replace("-", "") + "." + FilenameUtils.getExtension(file.getOriginalFilename());
        String fileSavePath = sdf.format(new Date()) + "/" +saveFileName;

        // 执行存储
        InputStream inputStream = null;
        boolean saveFlag = false;
        String saveMessage = "";
        try{
            HashMap<String, String> headMap = new HashMap<>();
            headMap.put("X-Amz-Acl","public-read");
            inputStream = file.getInputStream();
            PutObjectArgs args = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileSavePath)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .headers(headMap)
                    .build();
            client.putObject(args);
            saveFlag = true;
            saveMessage = "success";
        } catch (Exception e){
            saveMessage = e.getMessage();
            logger.error("上传文件到minio异常", e);
        } finally {
            if(inputStream != null){
                try{
                    inputStream.close();
                } catch (Exception e) {
                    logger.error("上传文件到minio时，断开输入流异常", e);
                }
            }
        }

        // 7. 构建结果对象
        FileInfoRespFile result = new FileInfoRespFile();
        result.setFileOriginalName(fileOriginalName);
        result.setFileSaveName(saveFileName);
        result.setFilePath(File.separator + bucketName + File.separator + fileSavePath);
        String completeUrl = baseSchema + baseUrl + File.separator + bucketName + File.separator + fileSavePath;
        result.setCompleteUrl(completeUrl);
        result.setServerUrl(baseSchema + baseUrl);
        result.setUploadSuccess(saveFlag);
        result.setUploadMessage(saveMessage);

        // 8. 保存到数据库

        // 9. 返回
        return result;
    }

    @Override
    public MultiFileUploadResp multiUpload(MultipartFile file) {
        return null;
    }

    @Override
    public BaseResult delete(String fileId) {
        return null;
    }

    @Override
    public BaseResult deleteByPath(String path) {
        return null;
    }

    @Override
    public String download(String fileId) {
        return "";
    }

    @Override
    public String downloadByPath(String path) {
        return "";
    }

    @Override
    public String watch(String fileId) {
        return "";
    }

    @Override
    public String watchByPath(String path) {
        return "";
    }

    @Override
    public FileInfoRespFile query(String fileId) {
        return null;
    }

    @Override
    public FileInfoRespFile queryByPath(String path) {
        return null;
    }
}
